home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / gfx / misc / gnuplot-3.7src.lha / gnuplot-3.7src / gnuplot-3.7.lha / gnuplot-3.7 / term / latex.trm (.txt) < prev    next >
LaTeX Document  |  1998-12-15  |  26KB  |  678 lines

  1.  * $Id: latex.trm,v 1.63 1998/04/14 00:17:53 drd Exp $
  2. /* GNUPLOT - latex.trm */
  3.  * Copyright 1990 - 1993, 1998
  4.  * Permission to use, copy, and distribute this software and its
  5.  * documentation for any purpose with or without fee is hereby granted,
  6.  * provided that the above copyright notice appear in all copies and
  7.  * that both that copyright notice and this permission notice appear
  8.  * in supporting documentation.
  9.  * Permission to modify the software is granted, but not the right to
  10.  * distribute the complete modified source code.  Modifications are to
  11.  * be distributed as patches to the released version.  Permission to
  12.  * distribute binaries produced by compiling modified sources is granted,
  13.  * provided you
  14.  *   1. distribute the corresponding source modifications from the
  15.  *    released version in the form of a patch file along with the binaries,
  16.  *   2. add special version identification to distinguish your version
  17.  *    in addition to the base release version number,
  18.  *   3. provide your name and address as the primary contact for the
  19.  *    support of your modified version, and
  20.  *   4. retain our contact information in regard to use of the base
  21.  *    software.
  22.  * Permission to distribute the released version of the source code along
  23.  * with corresponding source modifications in the form of a patch file is
  24.  * granted with same provisions 2 through 4 for binary distributions.
  25.  * This software is provided "as is" without express or implied warranty
  26.  * to the extent permitted by applicable law.
  27.  * This file is included by ../term.c.
  28.  * This terminal driver supports:
  29.  *   LaTeX pictures (latex).
  30.  *   LaTeX pictures with emTeX specials (emtex). 
  31.  * AUTHORS
  32.  *   David Kotz, Russell Lang
  33.  * send your comments or suggestions to (info-gnuplot@dartmouth.edu).
  34. /* modified to optimize use of \rule for long lines */
  35. /* TLDC: modified to have nice line types */
  36. /* the following LATEX driver has been modified by 
  37.    Russell Lang, eln272v@monu1.cc.monash.oz from the
  38.    GnuTeX 1.3 driver by David Kotz, David.Kotz@Dartmouth.edu.
  39.    Since then it has been further extended by David Kotz.
  40.    EmTeX driver by Russell Lang. */
  41. /*  9 Dec 1992  LATEX_put_text rewritten to handle \\ newlines
  42.                 Daniel S. Lewart (d-lewart@uiuc.edu) */
  43. /* Since it took me a little while to figure out what is happening,
  44.  * I may as well write it down.
  45.  *  There are three length scales of interest: inches, points
  46.  * and dots. inches are obvious. points are the usual typesetting
  47.  * thing (ie approx 72 points per inch). This driver works in
  48.  * units of dots, which corresponds to pixels on a 300 DPI printer.
  49.  * We do a \setlength{unitlength}{...pt} to make teX work in
  50.  * terms of dots.  The ... is called LATEX_UNIT in here.
  51.  *   The reason I had to get involved in all of this is because
  52.  * font size (in pts) was not being scaled up by DOTS_PER_POINT
  53.  * - drd, Sept 1996
  54. #include "driver.h"
  55. #ifdef TERM_REGISTER
  56. register_term(latex)
  57. #ifdef EMTEX
  58. register_term(emtex)
  59. #endif
  60. #endif
  61. #ifdef TERM_PROTO
  62. TERM_PUBLIC void LATEX_options __PROTO((void));
  63. TERM_PUBLIC void LATEX_init __PROTO((void));
  64. TERM_PUBLIC void LATEX_graphics __PROTO((void));
  65. TERM_PUBLIC void LATEX_text __PROTO((void));
  66. TERM_PUBLIC void LATEX_put_text __PROTO((unsigned int x, unsigned int y, char str[]));
  67. TERM_PUBLIC void LATEX_linetype __PROTO((int linetype));
  68. TERM_PUBLIC void LATEX_move __PROTO((unsigned int x, unsigned int y));
  69. TERM_PUBLIC void LATEX_point __PROTO((unsigned int x, unsigned int y, int number));
  70. TERM_PUBLIC void LATEX_vector __PROTO((unsigned int ux, unsigned int uy));
  71. TERM_PUBLIC void LATEX_arrow __PROTO((unsigned int sx, unsigned int sy, unsigned int ex, unsigned int ey, TBOOLEAN head));
  72. TERM_PUBLIC int LATEX_justify_text __PROTO((enum JUSTIFY mode));
  73. TERM_PUBLIC int LATEX_text_angle __PROTO((int ang));
  74. TERM_PUBLIC void LATEX_reset __PROTO((void));
  75. #ifdef EMTEX
  76. TERM_PUBLIC void EMTEX_init __PROTO((void));
  77. TERM_PUBLIC void EMTEX_reset __PROTO((void));
  78. TERM_PUBLIC void EMTEX_text __PROTO((void));
  79. #endif
  80. #define TINY_STEP 0.5        /* tiny steps for high quality lines */
  81. #define LATEX_PTS_PER_INCH (72.27)
  82. #define DOTS_PER_INCH (300)    /* resolution of printer we expect to use */
  83. #define LATEX_UNIT (LATEX_PTS_PER_INCH/DOTS_PER_INCH)    /* dot size in pt */
  84. /* 5 inches wide by 3 inches high (default) */
  85. #define LATEX_XMAX (5*DOTS_PER_INCH)    /* (LATEX_PTS_PER_INCH/LATEX_UNIT*5.0) */
  86. #define LATEX_YMAX (3*DOTS_PER_INCH)    /* (LATEX_PTS_PER_INCH/LATEX_UNIT*3.0) */
  87. #define LATEX_HTIC (5*DOTS_PER_INCH/72)        /* (5 pts) */
  88. #define LATEX_VTIC (5*DOTS_PER_INCH/72)        /* (5 pts) */
  89. #define LATEX_HCHAR (DOTS_PER_INCH*53/10/72)    /* (5.3 pts) */
  90. #define LATEX_VCHAR (DOTS_PER_INCH*11/72)    /* (11 pts) */
  91. #endif
  92. #ifndef TERM_PROTO_ONLY
  93. #ifdef TERM_BODY
  94. static int LATEX_posx;
  95. static int LATEX_posy;
  96. static int LATEX_fontsize = 10;
  97. static char LATEX_font[MAX_ID_LEN+1] = "cmr";
  98. static enum JUSTIFY latex_justify = LEFT;
  99. static int latex_angle = 0;
  100. /* Default line-drawing character */
  101. /* the definition of plotpoint varies with linetype */
  102. #define LATEX_DOT "\\usebox{\\plotpoint}"
  103. #define LATEX_TINY_DOT "\\rule{1pt}{1pt}"    /* for dots plot style */
  104. /* POINTS */
  105. #define LATEX_POINT_TYPES 12    /* we supply more point types */
  106. static char GPFAR *GPFAR LATEX_points[] =
  107.     "\\raisebox{-.8pt}{\\makebox(0,0){$\\Diamond$}}",
  108.     "\\makebox(0,0){$+$}",
  109.     "\\raisebox{-.8pt}{\\makebox(0,0){$\\Box$}}",
  110.     "\\makebox(0,0){$\\times$}",
  111.     "\\makebox(0,0){$\\triangle$}",
  112.     "\\makebox(0,0){$\\star$}",
  113.     "\\circle{12}", "\\circle{18}", "\\circle{24}",
  114.     "\\circle*{12}", "\\circle*{18}", "\\circle*{24}"
  115. /* LINES */
  116. static float LATEX_size = 0;    /* current thick of line in points */
  117. static float LATEX_dotspace = 0;    /* current dotspace of line in points */
  118. #define LATEX_LINE_TYPES 6    /* number of line types below */
  119. #define LATEX_THIN_LINE 0    /* the thinnest solid line type */
  120. static struct {
  121.     float size;            /* size of dot, or thick of line in points */
  122.     float dotspace;        /* inter-dot space in points; 0 for lines */
  123. } GPFAR LATEX_lines[] =
  124.     {0.4, 0.0},            /* thin solid line */
  125.     {0.4, 5.0},            /* thin dotted line */
  126.     {0.8, 0.0},            /* thick solid line */
  127.     {1.0, 5.0},            /* thick dotted line */
  128.     {1.2, 0.0},            /* Thick solid line */
  129.     {1.0, 10.0},        /* thick widely dotted line */
  130. /* for drawing dotted and solid lines */
  131. static void LATEX_dot_line __PROTO((int x1, int x2, int y1, int y2));
  132. static void LATEX_solid_line __PROTO((int x1, int x2, int y1, int y2));
  133. static void LATEX_rule __PROTO((int code, double x, double y, double width, double height));
  134. static void LATEX_flushdot __PROTO((void));
  135. #define LATEX_flushrule() LATEX_rule(2, 0.,0.,0.,0.)    /* flush old rule */
  136. static TBOOLEAN LATEX_moved = TRUE;    /* pen is up after move */
  137. static float LATEX_dotsize;    /* size of LATEX_DOT in units */
  138. static TBOOLEAN LATEX_needsdot = FALSE;        /* does dotted line need termination? */
  139. #ifdef EMTEX
  140. TBOOLEAN emtex = FALSE;        /* not currently using emtex */
  141. static void
  142. EMTEX_solid_line __PROTO((int x1, int x2, int y1, int y2));
  143. #endif
  144. /* ARROWS */
  145. /* the set of non-vertical/non-horizontal LaTeX vector slopes */
  146. /* except negatives - they are handled specially */
  147. static struct vslope {
  148.     int dx, dy;
  149. } GPFAR LATEX_slopes[] =
  150.     {1, 1},
  151.     {1, 2},
  152.     {1, 3},
  153.     {1, 4},
  154.     {2, 1},
  155.     {2, 3},
  156.     {3, 1},
  157.     {3, 2},
  158.     {3, 4},
  159.     {4, 1},
  160.     {4, 3},
  161.     {0, 0}            /* terminator */
  162. /* figure out the best arrow */
  163. void best_latex_arrow __PROTO((int, int, int, int, int, TBOOLEAN));
  164. TERM_PUBLIC void LATEX_options()
  165.     if (!END_OF_COMMAND) {
  166.     if (almost_equals(c_token, "c$ourier")) {
  167.         strcpy(LATEX_font, "cmtt");
  168.         c_token++;
  169.     } else if (almost_equals(c_token, "r$oman")) {
  170.         strcpy(LATEX_font, "cmr");
  171.         c_token++;
  172.     } else if (almost_equals(c_token, "d$efault")) {
  173.         strcpy(LATEX_font, "cmr");
  174.         LATEX_fontsize = 10;
  175.         c_token++;
  176.     }
  177.     if (!END_OF_COMMAND) {
  178.     struct value a;
  179.     LATEX_fontsize = (int) real(const_express(&a));
  180.     }
  181.     /* tell gnuplot core about char. sizes. Horizontal spacing
  182.      * is about half the text pointsize
  183.      */
  184.     term->v_char = (unsigned int) (LATEX_fontsize * DOTS_PER_INCH / 72);
  185.     term->h_char = (unsigned int) (LATEX_fontsize * DOTS_PER_INCH / 144);
  186.     sprintf(term_options, "%s %d", LATEX_font[2] == 't' ? "courier" : "roman",
  187.         LATEX_fontsize);
  188. TERM_PUBLIC void LATEX_init()
  189. #ifdef EMTEX
  190.     emtex = FALSE;
  191. #endif
  192.     LATEX_posx = LATEX_posy = 0;
  193.     fprintf(gpoutfile, "\
  194. %% GNUPLOT: LaTeX picture\n\
  195. \\setlength{\\unitlength}{%fpt}\n\
  196. \\ifx\\plotpoint\\undefined\\newsavebox{\\plotpoint}\\fi\n",
  197.         LATEX_UNIT);
  198.     LATEX_linetype(-1);
  199.     LATEX_size = 0;
  200. TERM_PUBLIC void LATEX_graphics()
  201.     register struct termentry *t = term;
  202.     /* bounding box */
  203.     int xscale = xsize * t->xmax;
  204.     int yscale = ysize * t->ymax;
  205.     fprintf(gpoutfile, "\
  206. \\begin{picture}(%d,%d)(0,0)\n\
  207. \\font\\gnuplot=%s10 at %dpt\n\
  208. \\gnuplot\n",
  209.         xscale, yscale,
  210.         LATEX_font, LATEX_fontsize);
  211. TERM_PUBLIC void LATEX_text()
  212.     LATEX_flushrule();
  213.     LATEX_flushdot();
  214.     fputs("\\end{picture}\n", gpoutfile);
  215.     LATEX_posx = LATEX_posy = 0;    /* current position */
  216.     LATEX_moved = TRUE;        /* pen is up after move */
  217. TERM_PUBLIC void LATEX_linetype(linetype)
  218. int linetype;
  219.     float size;
  220.     if (linetype >= LATEX_LINE_TYPES)
  221.     linetype %= LATEX_LINE_TYPES;
  222. #ifdef EMTEX
  223.     if (!emtex)
  224. #endif
  225.     LATEX_flushrule();
  226.     LATEX_flushdot();
  227.     /* Find the new desired line thickness. */
  228.     /* negative linetypes (for axes) use a thin line */
  229.     /* only relevant for drawing axes/border in 3d */
  230.     size = (linetype >= 0 ? LATEX_lines[linetype].size
  231.         : LATEX_lines[LATEX_THIN_LINE].size);
  232.     /* If different from current size, redefine \plotpoint */
  233.     if (size != LATEX_size) {
  234.     fprintf(gpoutfile,
  235.         "\\sbox{\\plotpoint}{\\rule[%.3fpt]{%.3fpt}{%.3fpt}}%%\n",
  236.         -size / 2, size, size);
  237. #ifdef EMTEX
  238.     if (emtex)        /* change line width */
  239.         fprintf(gpoutfile, "\\special{em:linewidth %.1fpt}%%\n", size);
  240. #endif
  241.     }
  242.     LATEX_size = size;
  243.     LATEX_dotsize = size / LATEX_UNIT;
  244.     LATEX_dotspace = (linetype >= 0) ? LATEX_lines[linetype].dotspace : 0;
  245.     LATEX_moved = TRUE;        /* reset */
  246. TERM_PUBLIC void LATEX_move(x, y)
  247. unsigned int x, y;
  248.     LATEX_flushdot();
  249.     LATEX_posx = x;
  250.     LATEX_posy = y;
  251.     LATEX_moved = TRUE;        /* reset */
  252. TERM_PUBLIC void LATEX_point(x, y, number) /* version of line_and_point */
  253. unsigned int x, y;
  254. int number;            /* type of point */
  255.     LATEX_move(x, y);
  256.     /* Print the character defined by 'number'; number < 0 means 
  257.        to use a dot, otherwise one of the defined points. */
  258.     fprintf(gpoutfile, "\\put(%d,%d){%s}\n", x, y,
  259.         (number < 0 ? LATEX_TINY_DOT
  260.          : LATEX_points[number % LATEX_POINT_TYPES]));
  261. TERM_PUBLIC void LATEX_vector(ux, uy)
  262. unsigned int ux, uy;
  263.     if (LATEX_dotspace == 0.0) {
  264.     /* solid line */
  265. #ifdef EMTEX
  266.     if (emtex)
  267.         EMTEX_solid_line(LATEX_posx, (int) ux, LATEX_posy, (int) uy);
  268.     else
  269. #endif
  270.         LATEX_solid_line(LATEX_posx, (int) ux, LATEX_posy, (int) uy);
  271.     } else
  272.     /* dotted line */
  273.     LATEX_dot_line(LATEX_posx, (int) ux, LATEX_posy, (int) uy);
  274.     LATEX_posx = ux;
  275.     LATEX_posy = uy;
  276. static void LATEX_solid_line(x1, x2, y1, y2)
  277. int x1, x2, y1, y2;
  278.     float slope;
  279.     int inc;
  280.     float dx, dy, x, y;
  281.     float offset, length;
  282.     int code;            /* possibly combine with previous rule */
  283.     /* we draw a solid line using the current line thickness (size) */
  284.     /* we do it with lots of \\rules */
  285.     if (x1 == x2 && y1 == y2) {    /* zero-length line - just a dot */
  286.     if (LATEX_moved) {
  287.         LATEX_flushrule();
  288.         /* plot a dot */
  289.         fprintf(gpoutfile, "\\put(%u,%u){%s}\n", x1, y1, LATEX_DOT);
  290.     } else {
  291.     code = (LATEX_moved ? 0 : 1);    /* no combine after move */
  292.     LATEX_moved = FALSE;
  293.     if (x1 == x2)        /* vertical line - special case */
  294.         LATEX_rule(code, (double) x1, (double) y1,
  295.                LATEX_dotsize, (double) y2 - y1);
  296.     else if (y1 == y2)    /* horizontal line - special case */
  297.         LATEX_rule(code, (double) x1, (double) y1, (double) x2 - x1,
  298.                LATEX_dotsize);
  299.     else {
  300.         dx = (float) x2 - x1;
  301.         dy = (float) y2 - y1;
  302.         slope = dy / dx;
  303.         if (ABS(slope) <= 1.0) {
  304.         /* longer than high */
  305.         x = GPMIN(ABS(dx), (0.25 + 1.0 / ABS(slope)) * LATEX_dotsize);
  306.         offset = sign(dy) * GPMIN(LATEX_dotsize, ABS(dy));
  307.         dy = dy - offset;
  308.         length = x * LATEX_UNIT;
  309.         inc = (x == ABS(dx) ? 1 : GPMAX(1, ABS(dy) / TINY_STEP + 0.5));
  310.         if (inc == 1) {
  311.             fprintf(gpoutfile, "\\put(%u,%.2f){\\rule{%.3fpt}{%.3fpt}}\n",
  312.                 (x2 >= x1 ? x1 : x2), ((float) y1 + y2 - LATEX_dotsize) / 2,
  313.                 length, LATEX_dotsize * LATEX_UNIT);
  314.         } else {
  315.             dy = dy / inc;
  316.             dx = (dx - sign(dx) * x) / (inc - 1);
  317.             fprintf(gpoutfile,
  318.                 "\\multiput(%.2f,%.2f)(%.3f,%.3f){%u}{\\rule{%.3fpt}{%.3fpt}}\n",
  319.                 (dx >= 0.0 ? (float) x1 : x1 - x),
  320.                 (float) y1 - (ABS(dy) - offset) / 2,
  321.                 dx, dy, inc, length, ABS(dy) * LATEX_UNIT);
  322. /* done with one section, now smooth it */
  323.         x = x / 2;
  324.         dx = sign(dx) * x;
  325.         dx = (float) x2 - x1 - dx;
  326.         dy = (float) y2 - y1;
  327.         fprintf(gpoutfile, "\\multiput(%.2f,%.2f)(%.3f,%.3f){2}{\\rule{%.3fpt}{%.3fpt}}\n",
  328.             (dx >= 0.0 ? (float) x1 : x1 - x), (float) y1 - LATEX_dotsize / 2,
  329.             dx, dy, x * LATEX_UNIT, LATEX_dotsize * LATEX_UNIT);
  330.         LATEX_moved = TRUE;
  331.         } else {
  332.         /* higher than long */
  333.         y = GPMIN(ABS(dy), (0.25 + ABS(slope)) * LATEX_dotsize);
  334.         offset = sign(dx) * GPMIN(LATEX_dotsize, ABS(dx));
  335.         dx = dx - offset;
  336.         length = y * LATEX_UNIT;
  337.         inc = (y == ABS(dy) ? 1 : GPMAX(1, ABS(dx) / TINY_STEP + 0.5));
  338.         if (inc == 1) {
  339.             fprintf(gpoutfile, "\\put(%.2f,%u){\\rule{%.3fpt}{%.3fpt}}\n",
  340.                 ((float) x1 + x2 - LATEX_dotsize) / 2, (y2 >= y1 ? y1 : y2),
  341.                 LATEX_dotsize * LATEX_UNIT, length);
  342.         } else {
  343.             dx = dx / inc;
  344.             dy = (dy - sign(dy) * y) / (inc - 1);
  345.             fprintf(gpoutfile,
  346.                 "\\multiput(%.2f,%.2f)(%.3f,%.3f){%u}{\\rule{%.3fpt}{%.3fpt}}\n",
  347.                 (float) x1 - (ABS(dx) - offset) / 2,
  348.                 (dy >= 0 ? (float) y1 : y1 - y),
  349.                 dx, dy, inc, ABS(dx) * LATEX_UNIT, length);
  350. /* done with one section, now smooth it */
  351.         y = y / 2;
  352.         dx = (float) x2 - x1;
  353.         dy = sign(dy) * y;
  354.         dy = (float) y2 - y1 - dy;
  355.         fprintf(gpoutfile, "\\multiput(%.2f,%.2f)(%.3f,%.3f){2}{\\rule{%.3fpt}{%.3fpt}}\n",
  356.             (float) x1 - LATEX_dotsize / 2, (dy >= 0.0 ? (float) y1 : y1 - y),
  357.             dx, dy, LATEX_dotsize * LATEX_UNIT, y * LATEX_UNIT);
  358.         LATEX_moved = TRUE;
  359.         }
  360.     }
  361. /* Draw a \rule. Width or height may be negative; we can correct.
  362.  * The rule is never output immediately. The previous rule is output
  363.  * as-is if code is 0, and the previous rule is
  364.  * combined with the current rule (if possible) if code is 1.
  365.  * The previous rule is output, and the new one ignored, if code is 2.
  366. static void LATEX_rule(code, x, y, width, height)
  367. int code;            /* how do we treat this rule? */
  368. double x, y;
  369. double width;
  370. double height;
  371.     static float lastx, lasty;
  372.     static float lastw, lasth;
  373.     static TBOOLEAN isvalid = FALSE;    /* is 'last' data valid? */
  374.     TBOOLEAN combine = (code == 1);
  375.     TBOOLEAN flush = (code == 2);
  376.     if (!flush)
  377.     if (width == 0 || height == 0)
  378.         return;        /* ignore this rule */
  379.     if (isvalid && combine) {
  380.     /* try to combine new rule with old rule */
  381.     if ((int) lastx == (int) x && lastw == width) {        /* vertical rule */
  382.         if (lasth * height >= 0) {    /* same sign */
  383.         lasth += height;
  384.         return;
  385.         }
  386.     } else if ((int) lasty == (int) y && lasth == height) {        /* horiz rule */
  387.         if (lastw * width >= 0) {    /* same sign */
  388.         lastw += width;
  389.         return;
  390.         }
  391.     /* oh well, output last and remember the new one */
  392.     }
  393.     if (isvalid) {
  394.     /* output the rule */
  395.     if (lastw < 0) {
  396.         lastx += lastw;
  397.         lastw = -lastw;
  398.     if (lasth < 0) {
  399.         lasty += lasth;
  400.         lasth = -lasth;
  401.     /* if very small use canned dot */
  402.     if (lastw < LATEX_dotsize || lasth < LATEX_dotsize)
  403.         fprintf(gpoutfile, "\\put(%.1f,%.1f){%s}\n",
  404.             lastx, lasty, LATEX_DOT);
  405.     else
  406.         fprintf(gpoutfile, "\\put(%.1f,%.1f){\\rule[%.3fpt]{%.3fpt}{%.3fpt}}\n",
  407.             lastx, lasty, -LATEX_dotsize * LATEX_UNIT / 2,
  408.             lastw * LATEX_UNIT, lasth * LATEX_UNIT);
  409.     }
  410.     if (flush) {
  411.     isvalid = FALSE;
  412.     } else {
  413.     lastx = x;
  414.     lasty = y;
  415.     lastw = width;
  416.     lasth = height;
  417.     isvalid = TRUE;
  418.     }
  419. static void LATEX_dot_line(x1, x2, y1, y2)
  420. int x1, x2, y1, y2;
  421.     static float LATEX_left;    /* fraction of space left after last dot */
  422.     /* we draw a dotted line using the current dot spacing */
  423.     if (LATEX_moved)
  424.     LATEX_left = 1.0;    /* reset after a move */
  425.     /* zero-length line? */
  426.     if (x1 == x2 && y1 == y2) {
  427.     if (LATEX_moved)
  428.         /* plot a dot */
  429.         fprintf(gpoutfile, "\\put(%u,%u){%s}\n", x1, y1, LATEX_DOT);
  430.     } else {
  431.     float dotspace = LATEX_dotspace / LATEX_UNIT;
  432.     float x, y;        /* current position */
  433.     float xinc, yinc;    /* increments */
  434.     float slope;        /* slope of line */
  435.     float lastx = -1;    /* last x point plotted */
  436.     float lasty = -1;    /* last y point plotted */
  437.     int numdots = 0;    /* number of dots in this section */
  438.     /* first, figure out increments for x and y */
  439.     if (x2 == x1) {
  440.         xinc = 0.0;
  441.         yinc = (y2 - y1 > 0) ? dotspace : -dotspace;
  442.     } else {
  443.         slope = ((float) y2 - y1) / ((float) x2 - x1);
  444.         xinc = dotspace / sqrt(1 + slope * slope) * sign(x2 - x1);
  445.         yinc = slope * xinc;
  446.     /* now draw the dotted line */
  447.     /* we take into account where we last placed a dot */
  448.     for (x = x1 + xinc * (1 - LATEX_left), y = y1 + yinc * (1 - LATEX_left);
  449.          (x2 - x) * xinc >= 0 && (y2 - y) * yinc >= 0;    /* same sign or zero */
  450.          lastx = x, x += xinc,
  451.          lasty = y, y += yinc)
  452.         numdots++;
  453.     if (numdots == 1)
  454.         fprintf(gpoutfile, "\\put(%.2f,%.2f){%s}\n",
  455.             lastx, lasty, LATEX_DOT);
  456.     else if (numdots > 0)
  457.         fprintf(gpoutfile, "\\multiput(%u,%u)(%.3f,%.3f){%u}{%s}\n",
  458.             x1, y1, xinc, yinc, numdots, LATEX_DOT);
  459.     /* how much is left over, as a fraction of dotspace? */
  460.     if (xinc != 0.0)    /* xinc must be nonzero */
  461.         if (lastx >= 0)
  462.         LATEX_left = ABS(x2 - lastx) / ABS(xinc);
  463.         else
  464.         LATEX_left += ABS(x2 - x1) / ABS(xinc);
  465.     else if (lasty >= 0)
  466.         LATEX_left = ABS(y2 - lasty) / ABS(yinc);
  467.     else
  468.         LATEX_left += ABS(y2 - y1) / ABS(yinc);
  469.     }
  470.     LATEX_needsdot = (LATEX_left > 0);
  471.     LATEX_moved = FALSE;
  472. static void LATEX_flushdot()
  473.     if (LATEX_needsdot)
  474.     fprintf(gpoutfile, "\\put(%d,%d){%s}\n",
  475.         LATEX_posx, LATEX_posy, LATEX_DOT);
  476.     LATEX_needsdot = FALSE;
  477. TERM_PUBLIC void LATEX_arrow(sx, sy, ex, ey, head)
  478. unsigned int sx, sy, ex, ey;
  479. TBOOLEAN head;
  480.     best_latex_arrow(sx, sy, ex, ey, 1, head);
  481.     LATEX_posx = ex;
  482.     LATEX_posy = ey;
  483. void best_latex_arrow(sx, sy, ex, ey, who, head)
  484. int sx, sy, ex, ey;        /* start and end points */
  485. int who;            /* 1=LATEX, 2=EEPIC */
  486. TBOOLEAN head;
  487.     int dx = ex - sx;
  488.     int dy = ey - sy;
  489.     float m;            /* slope of line */
  490.     float arrowslope;        /* slope of arrow */
  491.     float minerror = 0;        /* best-case error */
  492.     struct vslope *slope;    /* one of the slopes */
  493.     struct vslope *bestslope;    /* the slope with min error */
  494.     /* We try to draw a real arrow (ie, \vector). If we can't get
  495.        * a slope that is close, we draw a bent arrow.
  496.      */
  497.     if (dx == 0) {
  498.     /* vertical arrow */
  499.     fprintf(gpoutfile, "\\put(%d,%d){\\%s(0,%d){%d}}\n",
  500.         sx, sy, head ? "vector" : "line",
  501.         sign(ey - sy), ABS(ey - sy));
  502.     } else if (dy == 0) {
  503.     /* horizontal arrow */
  504.     fprintf(gpoutfile, "\\put(%d,%d){\\%s(%d,0){%d}}\n",
  505.         sx, sy, head ? "vector" : "line",
  506.         sign(ex - sx), ABS(ex - sx));
  507.     } else {
  508.     /* Slanted arrow. We'll give it a try.
  509.      * we try to find the closest-slope arrowhead.
  510.     bestslope = NULL;
  511.     minerror = 0;        /* to shut up turbo C */
  512.     m = ABS((float) dy / dx);    /* the slope we want */
  513.     for (slope = LATEX_slopes; slope->dx != 0.0; slope++) {
  514.         /* find the slope of the arrow */
  515.         arrowslope = (float) slope->dy / slope->dx;
  516.         if (bestslope == NULL || ABS(m - arrowslope) < minerror) {
  517.         minerror = ABS(m - arrowslope);
  518.         bestslope = slope;
  519.         }
  520.     /* now we have the best slope arrow */
  521.     /* maybe it's exactly the right slope! */
  522.     if (minerror == 0.0)    /* unlikely but possible */
  523.         fprintf(gpoutfile, "\\put(%d,%d){\\%s(%d,%d){%d}}\n",
  524.             sx, sy, head ? "vector" : "line",
  525.             bestslope->dx * sign(ex - sx), bestslope->dy * sign(ey - sy),
  526.             ABS(ex - sx));
  527.     else {
  528.         /* we draw the line the usual way, with thin lines */
  529. #ifdef EMTEX
  530.         if (emtex) {
  531.         LATEX_linetype(LATEX_THIN_LINE);
  532.         EMTEX_solid_line(sx, ex, sy, ey);
  533.         } else
  534. #endif
  535.         if (who == 1) {
  536.         LATEX_linetype(LATEX_THIN_LINE);
  537.         LATEX_solid_line(sx, ex, sy, ey);
  538.         }
  539. #ifdef EEPIC
  540.         else {
  541.         EEPIC_move(sx, sy);
  542.         EEPIC_vector(ex, ey);
  543.         }
  544. #endif /* EEPIC */
  545.         /* and then draw an arrowhead (a short vector) there */
  546.         if (head)
  547.         fprintf(gpoutfile, "\\put(%d,%d){\\vector(%d,%d){0}}\n",
  548.             ex, ey,
  549.             bestslope->dx * sign(ex - sx), bestslope->dy * sign(ey - sy));
  550.     }
  551. TERM_PUBLIC void LATEX_put_text(x, y, str)
  552. unsigned int x, y;        /* reference point of string */
  553. char str[];            /* the text */
  554.     static char *justify[] =
  555.     {"[l]", "", "[r]"};
  556.     int flag, i;
  557.     /* ignore empty strings */
  558.     if (str[0] == NUL)
  559.     return;
  560.     for (flag = FALSE, i = 0; str[i] && !flag;)
  561.     flag = (str[i++] == '\\') && (str[i++] == '\\');
  562.     fprintf(gpoutfile, "\\put(%d,%d)", x, y);
  563.     if ((str[0] == '{') || (str[0] == '[')) {
  564.     fprintf(gpoutfile, "{\\makebox(0,0)%s}\n", str);
  565.     } else if (flag)
  566.     fprintf(gpoutfile, "{\\makebox(0,0)%s{\\shortstack{%s}}}\n",
  567.         justify[latex_justify], str);
  568.     else
  569.     fprintf(gpoutfile, "{\\makebox(0,0)%s{%s}}\n",
  570.         justify[latex_justify], str);
  571. TERM_PUBLIC int LATEX_justify_text(mode)
  572. enum JUSTIFY mode;
  573.     latex_justify = mode;
  574.     return (TRUE);
  575. TERM_PUBLIC int LATEX_text_angle(ang)
  576. int ang;
  577.     /* we can't really write text vertically, but this will 
  578.        put the ylabel centred at the left of the plot, and
  579.        then we'll make a \shortstack */
  580.     latex_angle = ang;
  581.     return (TRUE);
  582. TERM_PUBLIC void LATEX_reset()
  583.     LATEX_posx = LATEX_posy = 0;    /* current position */
  584.     LATEX_moved = TRUE;        /* pen is up after move */
  585. #ifdef EMTEX
  586. TERM_PUBLIC void EMTEX_init()
  587.     emtex = TRUE;
  588.     LATEX_posx = LATEX_posy = 0;
  589.     fprintf(gpoutfile, "\
  590. %% GNUPLOT: LaTeX picture with emtex specials\n\
  591. \\setlength{\\unitlength}{%fpt}\n\
  592. \\ifx\\plotpoint\\undefined\\newsavebox{\\plotpoint}\\fi\n",
  593.         LATEX_UNIT);
  594.     LATEX_linetype(-1);
  595. TERM_PUBLIC void EMTEX_reset()
  596.     emtex = FALSE;
  597.     LATEX_posx = LATEX_posy = 0;
  598. TERM_PUBLIC void EMTEX_text()
  599.     fputs("\\end{picture}\n", gpoutfile);
  600. static void EMTEX_solid_line(x1, x2, y1, y2)
  601. int x1, x2, y1, y2;
  602.     /* emtex special solid line */
  603.     if (LATEX_moved)
  604.     fprintf(gpoutfile, "\\put(%d,%d){\\special{em:moveto}}\n", x1, y1);
  605.     if ((x1 != x2) || (y1 != y2))
  606.     fprintf(gpoutfile, "\\put(%d,%d){\\special{em:lineto}}\n", x2, y2);
  607.     LATEX_posx = x2;
  608.     LATEX_posy = y2;
  609.     LATEX_moved = FALSE;
  610. #endif /* EMTEX */
  611. #endif /* TERM_BODY */
  612. #endif /* TERM_PROTO_ONLY */
  613. #ifdef TERM_TABLE
  614. TERM_TABLE_START(latex_driver)
  615.     "latex", "LaTeX picture environment",
  616.     LATEX_XMAX, LATEX_YMAX, LATEX_VCHAR, LATEX_HCHAR,
  617.     LATEX_VTIC, LATEX_HTIC, LATEX_options, LATEX_init, LATEX_reset,
  618.     LATEX_text, null_scale, LATEX_graphics, LATEX_move, LATEX_vector,
  619.     LATEX_linetype, LATEX_put_text, LATEX_text_angle,
  620.     LATEX_justify_text, LATEX_point, LATEX_arrow, set_font_null
  621. TERM_TABLE_END(latex_driver)
  622. #undef LAST_TERM
  623. #define LAST_TERM latex_driver
  624. #ifdef EMTEX
  625. TERM_TABLE_START(emtex_driver)
  626.     "emtex", "LaTeX picture environment with emTeX specials",
  627.     LATEX_XMAX, LATEX_YMAX, LATEX_VCHAR, LATEX_HCHAR,
  628.     LATEX_VTIC, LATEX_HTIC, LATEX_options, EMTEX_init, EMTEX_reset,
  629.     EMTEX_text, null_scale, LATEX_graphics, LATEX_move, LATEX_vector,
  630.     LATEX_linetype, LATEX_put_text, LATEX_text_angle,
  631.     LATEX_justify_text, LATEX_point, LATEX_arrow, set_font_null
  632. TERM_TABLE_END(emtex_driver)
  633. #undef LAST_TERM
  634. #define LAST_TERM emtex_driver
  635. #endif /* EMTEX */
  636. #endif /* TERM_TABLE */
  637. #ifdef TERM_HELP
  638. START_HELP(latex)
  639. "1 latex",
  640. "?commands set terminal emtex",
  641. "?set terminal emtex",
  642. "?set term emtex",
  643. "?terminal emtex",
  644. "?term emtex",
  645. "?latex",
  646. "?commands set terminal latex",
  647. "?set terminal latex",
  648. "?set term latex",
  649. "?terminal latex",
  650. "?term latex",
  651. "?emtex",
  652. " The `latex` and `emtex` drivers allow two options.",
  653. " Syntax:",
  654. "       set terminal latex | emtex {courier | roman} {<fontsize>}",
  655. " `fontsize` may be any size you specify.  The default is 10-point Roman.",
  656. " Unless your driver is capable of building fonts at any size (e.g. dvips),",
  657. " stick to the standard 10, 11 and 12 point sizes.",
  658. " METAFONT users beware: METAFONT does not like odd sizes.",
  659. " All drivers for LaTeX offer a special way of controlling text positioning:",
  660. " If any text string begins with '{', you also need to include a '}' at the",
  661. " end of the text, and the whole text will be centered both horizontally",
  662. " and vertically by LaTeX. --- If the text string begins with '[', you need",
  663. " to continue it with: a position specification (up to two out of t,b,l,r),",
  664. " ']{', the text itself, and finally, '}'. The text itself may be anything",
  665. " LaTeX can typeset as an LR-box. \\rule{}{}'s may help for best positioning.",
  666. " Examples:",
  667. " About label positioning:",
  668. " Use gnuplot defaults (mostly sensible, but sometimes not really best):",
  669. "        set title '\\LaTeX\\ -- $ \\gamma $'",
  670. " Force centering both horizontally and vertically:",
  671. "        set label '{\\LaTeX\\ -- $ \\gamma $}' at 0,0",
  672. " Specify own positioning (top here):",
  673. "        set xlabel '[t]{\\LaTeX\\ -- $ \\gamma $}'",
  674. " The other label -- account for long ticlabels:",
  675. "        set ylabel '[r]{\\LaTeX\\ -- $ \\gamma $\\rule{7mm}{0pt}'"
  676. END_HELP(latex)
  677. #endif /* TERM_TABLE */
  678.